package com.hzlj.position.config.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.fz.common.dict.annotation.DictConvert;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.RateLimiter;
import com.hzlj.position.config.common.dto.operatorConfig.OperatorConfigQueryResultDTO;
import com.hzlj.position.config.dao.OperatorConfigDao;
import com.hzlj.position.config.rest.operator.OperatorLocateRest;
import com.hzlj.position.config.service.OperatorConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 定位-运营商配置表(OperatorConfig)表服务接口
 *
 * @author lifh
 * @date 2023-03-30 17:51:33
 */
@Slf4j
@Service
public class OperatorConfigServiceImpl implements OperatorConfigService {
    private final Map<String, List<OperatorTaskConfig>> operatorLocateRests = Maps.newConcurrentMap();
    @Resource
    private OperatorConfigDao operatorConfigDao;
    @Resource
    private ApplicationContext applicationContext;

    @PostConstruct
    private void init() {
        List<OperatorConfigQueryResultDTO> configs = this.listOperatorConfig();
        for (OperatorConfigQueryResultDTO config : configs) {
            String handler = StrUtil.lowerFirst(config.getHandler());
            if (!applicationContext.containsBean(handler)) {
                log.warn("运营商定位没有包含处理器:{}", config);
                continue;
            }
            OperatorLocateRest rest = applicationContext.getBean(handler, OperatorLocateRest.class);
            List<OperatorTaskConfig> list = operatorLocateRests.computeIfAbsent(config.getChannel(), (s) -> Lists.newCopyOnWriteArrayList());
            //默认每秒100
            BigDecimal limitForSecond = config.getLocateRequestLimitPerSecond();
            if (ObjectUtil.isEmpty(limitForSecond) || limitForSecond.compareTo(BigDecimal.ZERO) <= 0) {
                limitForSecond = new BigDecimal(100);
            }
            RateLimiter rateLimiter = RateLimiter.create(limitForSecond.doubleValue(), 10, TimeUnit.SECONDS);
            list.add(new OperatorTaskConfig(rest, config, rateLimiter));
            list.sort((a, b) -> b.getConfig().getJgCode().compareTo(a.getConfig().getJgCode()));
        }
    }

    /**
     * 查询列表：不分页
     */
    @Override
    @DictConvert
    public List<OperatorConfigQueryResultDTO> listOperatorConfig() {
        return this.operatorConfigDao.listOperatorConfig();
    }

    @Override
    public List<String> channels() {
        return listOperatorConfig().stream().map(OperatorConfigQueryResultDTO::getChannel).collect(Collectors.toList());
    }

    @Override
    public List<OperatorTaskConfig> taskConfigs() {
        return operatorLocateRests.values().stream().flatMap(Collection::stream).collect(Collectors.toList());
    }

    @Override
    public OperatorTaskConfig taskConfig(String jgCode, String channel) {
        List<OperatorTaskConfig> configs = operatorLocateRests.get(channel);
        if (configs == null) {
            log.warn("运营商定位没有包含处理器:channel={}", channel);
            return null;
        }

        for (OperatorTaskConfig config : configs) {
            if (jgCode.startsWith(config.getConfig().getJgCode())) {
                return config;
            }
        }
        log.warn("运营商定位没有包含处理器:jgCode={},channel={}", jgCode, channel);
        return null;
    }
}
